/*
 * Copyright 2010 Marcin Blazejewski
 *
 * This file is part of Nofate.
 *
 * Nofate is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Nofate is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nofate. If not, see <http://www.gnu.org/licenses/>.
 *
 */



/*
 * am_create()                      // create a map
 * am_fill(), am_set()              // put items on map
 * am_set_ambient(), am_light_add() // set lightning
 * am_relight()                     // apply light changes
 * 
 * mv_create()                      // create a map view
 * fov_map()                        // discover area map and fill map view
 * RE: re_draw_view()               // draw discovered map piece
 * ...
 * am_light_move(), am_set()        // [ change map ]
 * fov_map()                        // discover another piece of map
 * RE: re_draw_view()               // draw discovered map piece
 * ...
 * mv_destroy()
 * am_destroy()
 * 
 * --------------------------------------------------------------------
 * fov_init(), fov_end() are called internally by fov_* 
 * fov_light is called internally by am_relight()
 * 
 * !! Colors in re_putchar and re_puts are RGB
 * !! Colors in am_set() are HSV !!
 *
 * HSV colors: 0xHHHHSSVV
 *   HHHH: 0 - 360
 *   SS:   0 - 255
 *   VV:   0 - 255
 */

#ifndef RE_MAP_H_
#define RE_MAP_H_

#include <abstract/thing.hpp>
#include <abstract/action.hpp>
#include <list>

using namespace std;

typedef struct
{
    int                 x, y;
    int                 value;
    int                 cutoff;
} Light;

typedef struct MapCell_t {
    char                alpha;      // cell opacity 0 (empty) - 100 (filled)
    char                light;      // light level 0-100
    int                 bg;         // background color
    class Thing         *terrain;
} MapCell;

class AreaMapRow {
private:
    static MapCell      invalid;

public:
    int                 size;
    MapCell             *row;
    AreaMapRow(int _size, MapCell *_r);
    MapCell& operator[](int i);
};

class AreaMap {
private:
    static AreaMapRow         invalid;
public:
    int                       width, height;
    MapCell                   **cells;
    int                       ambient_light;
    Light*                    lights[50];
    list<class Thing*>        terrains;
    list<class Thing*>        things;
    list<class Action*>       events;

    AreaMap(const int w, const int h);
    ~AreaMap();

    AreaMapRow                operator[](int i);

    /* objs */
    void                     add_thing(Thing *t);
    void                     remove_thing(Thing *t);
    void                     move_thing(Thing *t, int x, int y);
    void                     ter_set(int x, int y, Thing *t, int bg=-1);
    void                     ter_fill(Thing *ter);

    /* light */    
    void                     set_ambient(char light);
    int                      light_add(int x, int y, int value, int cutoff);
    int                      light_remove(int l);
    void                     relight();
    /* life */
    int                      add_action(Action *a, Creature *cre);
    int                      tick();
};


class MapView {
public:
    // source data
    AreaMap                   &source;
    // 2D array of fov states: FOV_*
    char                      **fovmap;

    MapView(AreaMap &source);
    ~MapView();
};

/*
 * fov_init, fov_end - initialize/drop internal fov structures
 * fov_map - run FOV for map view (determine visible fields)
 * fov_ligt - run FOV to apply given light to map
 */
int             fov_init(int width, int height);
void            fov_end();
void            fov_map(MapView *mv, int ox, int oy, int maxDistance);
void            fov_light(AreaMap *am, Light *light);

#endif
